<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>es6 对象访问器方法</title>
  <!-- 
  在 JavaScript ES6 中，对象访问器方法（也称为 getter 和 setter）允许我们定义对象属性的访问和赋值行为。这种机制为对象的属性提供了更灵活的控制方式。
  1. 基本概念
  - 访问器属性：使用  `get`  和  `set`  关键字定义的属性，这些属性不直接存储值，而是通过函数来访问和设置值。
  - getter：用于读取属性值的方法。
  - setter：用于设置属性值的方法。

  2. 定义访问器方法
  可以在对象字面量中定义访问器方法，或者在类中定义它们。

   2.1 在对象字面量中定义
  使用  `get`  和  `set`  关键字来定义访问器属性。
  const person = {
      firstName: 'John',
      lastName: 'Doe',
      
      // Getter
      get fullName() {
          return `${this.firstName} ${this.lastName}`;
      },
      
      // Setter
      set fullName(name) {
          [this.firstName, this.lastName] = name.split(' ');
      }
  };

  // 使用 getter
  console.log(person.fullName); // 输出: John Doe

  // 使用 setter
  person.fullName = 'Jane Smith';
  console.log(person.firstName); // 输出: Jane
  console.log(person.lastName);  // 输出: Smith
   2.2 在类中定义
  在类中定义访问器方法的方式与对象字面量类似。
  class Person {
      constructor(firstName, lastName) {
          this.firstName = firstName;
          this.lastName = lastName;
      }

      // Getter
      get fullName() {
          return `${this.firstName} ${this.lastName}`;
      }

      // Setter
      set fullName(name) {
          [this.firstName, this.lastName] = name.split(' ');
      }
  }

  const alice = new Person('Alice', 'Johnson');

  // 使用 getter
  console.log(alice.fullName); // 输出: Alice Johnson

  // 使用 setter
  alice.fullName = 'Alice Brown';
  console.log(alice.firstName); // 输出: Alice
  console.log(alice.lastName);  // 输出: Brown
  3. 优缺点
  - 优点：
    - 封装性：通过访问器方法，可以控制属性的访问和修改，增强了数据的封装性。
    - 动态计算：getter 可以根据其他属性的值动态计算并返回结果。
    - 数据验证：setter 可以对传入的值进行验证和处理。

  - 缺点：
    - 性能开销：访问器方法在访问属性时会引入额外的函数调用，可能会影响性能。
    - 可读性：如果使用不当，可能会导致代码的可读性降低。

  4. 总结
  ES6 中的对象访问器方法（getter 和 setter）提供了一种灵活的方式来控制对象属性的访问和赋值行为。通过这些方法，开发者可以增强数据的封装性和安全性，实现更复杂的逻辑。理解访问器方法的使用对于编写高效和可维护的 JavaScript 代码非常重要。
   -->
</head>
<body>

  <script>
    // 针对对象
    // 方式一: 属性描述符
    const person = {
      _name: '张三',
    }
    Object.defineProperty(person, 'name', {
      get() {
        return this._name
      },
      set(value) {
        this._name = value
      }
    })
    console.log(person.name)
    person.name = '李四'
    console.log(person.name)
    
    // 方式二: es6
    const person2 = {
      _name: '张三',
      get name() {
        return this._name
      },
      set name(value) {
        this._name = value
      }
    }

    console.log(person2.name)
    person2.name = '李四'
    console.log(person2.name)
   
  </script>
  
</body>
</html>